package com.wolfking.converter.spring;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.type.filter.AnnotationTypeFilter;

import java.util.Arrays;
import java.util.Set;

/**
 * Import的spi scanner 自动注册spring的bean
 * 经过隔壁老王处理的JDK动态代理的版本控制扫描器
 *
 * @author 赵伟伟(wolfking)
 * created on 2019-09-29 13:33
 * Email is zhaoweiwei@youxin.com
 * Copyright is 友信金服
 */
@Slf4j
class ConverterSelectorScanner extends ClassPathBeanDefinitionScanner {

    ConverterSelectorScanner(BeanDefinitionRegistry registry) {
        super(registry, false);
    }

    /**
     * Calls the parent search that will search and register all the candidates.
     * Then the registered objects are post processed to set them as
     * SpiSelectorFactoryBeans
     */
    @Override
    public Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
        if (beanDefinitions.isEmpty()) {
            log.warn("no converter interface was found in {} package. Please check your configuration.", Arrays.toString(basePackages));
        } else {
            log.info("find total {} converter interface", beanDefinitions.size());
            beanDefinitions.forEach(this::assemblyBeanDefinition); /*注册bean*/
        }
        return beanDefinitions;
    }

    /**
     * 构建spring注册bean的信息
     * 设置 @Primary属性
     * 使用工厂类创建
     *
     * @param holder spring注册bean的holder
     */
    private void assemblyBeanDefinition(BeanDefinitionHolder holder) {
        /*scan的bean都是GenericBeanDefinition类型*/
        GenericBeanDefinition definition = GenericBeanDefinition.class.cast(holder.getBeanDefinition());
        String spiInterface = definition.getBeanClassName();
        log.info("register the converter interface is {}", spiInterface);
        /*设置工厂类的class*/
        definition.setBeanClass(ConverterProxyFactory.class);
        /*设置构造参数的class*/
        definition.getConstructorArgumentValues().addGenericArgumentValue(spiInterface);
        /*设置自动注入的类型，根据Type*/
        definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
        /*设置Primary属性，相当于@Primary注解*/
        definition.setPrimary(true);
        log.info("register the converter interface {} success", spiInterface);
    }

    /**
     * 注册扫描的过滤器
     */
    void registerFilters() {
        /*添加SpiInterface的的注解过滤器*/
        addIncludeFilter(new AnnotationTypeFilter(ConverterInterface.class));
        /*添加package-info的过滤器*/
        addExcludeFilter((reader, factory) -> reader.getClassMetadata().getClassName().endsWith("package-info"));
    }


    /**
     * 是否是spring的注册bean
     *
     * @param beanDefinition bean的定义
     * @return 是否是托管给spring管理的Bean
     */
    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();
    }
}
